package org.lojzesframework.minimongodb;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import com.google.gson.Gson;

public class MiniMongoDB extends AbstractMongoDB {
     /**
      * 约束：object 数据必须有一个id属性，作为唯一性约束
      *  
      */
	 private static String id = "id";
	//private static String uuid = "uuid";

	public MiniMongoDB(String dbName, String dbPath) {
		super(dbName, dbPath);
	}
    /**
     * 创建数据库
     * @param miniMongoDB
     * @return
     */
	public MiniMongoDB createDataBase() {
		try {
			FileOutputStream out = new FileOutputStream(new File(dbPath));
			Document document = new Document();
			Element root = new Element("db");
			document.setRootElement(root);
			XMLOutputter xmlOutputter = new XMLOutputter();
			xmlOutputter.output(document, out);
			System.out.println("===>>create database successfull...");
		} catch (Exception e) {
			e.printStackTrace();
		}
       return this;
	}
	/**
	 * 创建表
	 * @param tableName
	 */
	public void createTable(String tableName){
		try {
			FileInputStream in = new FileInputStream(new File(dbPath));
			SAXBuilder saxBuilder = new SAXBuilder();
			Document document = saxBuilder.build(in);
			Element root = document.getRootElement();
			Element table = new Element("table");
			table.setAttribute("name", tableName);
			root.addContent(table);
			XMLOutputter xmlOutputter = new XMLOutputter();
			xmlOutputter.output(document, new FileOutputStream(new File(dbPath)));
			System.out.println("===>>create table successfull...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    /**
     * 获取数据库下指定表明的数据
     * @param miniMongoDB
     * @param tableName
     * @return
     */
	public List<Map> loadTableDatas(MiniMongoDB miniMongoDB, String tableName) {
		Document document = getDocument(miniMongoDB);
		Element root = document.getRootElement();
		List<Element> tables = root.getChildren();
		List<Map> list = new ArrayList<Map>();
		Gson gson = new Gson();
		for (Element table : tables) {
			if (table.getAttributeValue("name").equals(tableName)) {
				String data = table.getText();
				Map fromJson = gson.fromJson(data, Map.class);
				list.add(fromJson);
			}
		}
		return list;
	}
    /**
     * 添加数据
     * @param miniMongoDB
     * @param tableName
     * @param object
     * @return
     */
	public boolean addData(MiniMongoDB miniMongoDB,String tableName,Object object){
		Document document = getDocument(miniMongoDB);
		Element root = document.getRootElement();
		List<Element> tables = root.getChildren();
		boolean flag=true;
		boolean isHasTable=false;
		Gson gson = new Gson();
		try {
			for (Element table : tables) {
				if(table.getAttributeValue("name").equals(tableName)){
					// base = new HashMap();
					Element data = new Element("data");
					//base.put(uuid, UUID.randomUUID().toString());
					String json = gson.toJson(object);
					//Map fromJson = gson.fromJson(json, Map.class);
					//base.putAll(fromJson);
					data.addContent(gson.toJson(json));
					table.addContent(data);
					isHasTable = true;
				}
			}
			if(!isHasTable){
				System.out.println("===>>insert data failed...");
				throw new Exception("===>>insert data failed...");
			}
			outXML(document, miniMongoDB);
			System.out.println("===>>insert data successfull...");
		} catch (Exception e) {
			e.printStackTrace();
			flag = false;
		}
		return flag;
	}
	/**
	 * 更新数据库表
	 * @param miniMongoDB
	 * @param tableName
	 * @param object
	 * @return
	 */
	public boolean updateData(MiniMongoDB miniMongoDB,String tableName,Object object){
		Document document = getDocument(miniMongoDB);
		Element root = document.getRootElement();
		List<Element> tables = root.getChildren();
		boolean isHasTable=false;
		boolean flag=true;
		Gson gson = new Gson();
		try {
			for (Element table : tables) {
				if(table.getAttributeValue("name").equals(tableName)){
					List<Element> datas = table.getChildren();
					for (Element data : datas) {
						Map oldData = gson.fromJson(data.getText(),Map.class);
						Map newData = gson.fromJson(gson.toJson(object), Map.class);
						if(oldData.get(id).equals(newData.get(id))){
							data.removeContent();
							data.addContent(gson.toJson(newData));
							isHasTable = true;
							break;
						}
					}
				}
			}
			outXML(document, miniMongoDB);
		} catch (Exception e) {
			flag = false;
			System.out.println("===>>updateData data failed...");
			e.printStackTrace();
		}
		if(!isHasTable){
			System.out.println("===>>updateData data failed...");
		}
		return flag;
	}
	/**
	 * 输出数据
	 * @param miniMongoDB
	 * @param tableName
	 * @param object
	 * @return
	 */
	public boolean deleteData(MiniMongoDB miniMongoDB,String tableName,Object object){
		Document document = getDocument(miniMongoDB);
		Element root = document.getRootElement();
		List<Element> tables = root.getChildren();
		boolean isHasTable=false;
		boolean flag=true;
		Gson gson = new Gson();
		try {
			for (Element table : tables) {
				if(table.getAttributeValue("name").equals(tableName)){
					List<Element> datas = table.getChildren();
					for (Element data : datas) {
						Map oldData = gson.fromJson(data.getText(),Map.class);
						Map newData = gson.fromJson(gson.toJson(object), Map.class);
						if(oldData.get(id).equals(newData.get(id))){
							data.removeContent();
							isHasTable = true;
							break;
						}
					}
				}
			}
			outXML(document, miniMongoDB);
		} catch (Exception e) {
			flag = false;
			System.out.println("===>>deleteData data failed...");
			e.printStackTrace();
		}
		if(!isHasTable){
			System.out.println("===>>deleteData data failed...");
		}
		return flag;
		
	}
	/**
	 * 得到document对象
	 * @param miniMongoDB
	 * @return
	 */
	private Document getDocument(MiniMongoDB miniMongoDB) {
		Document document = null;
		try {
			FileInputStream in = new FileInputStream(new File(miniMongoDB.dbPath));
			SAXBuilder saxBuilder = new SAXBuilder();
			document = saxBuilder.build(in);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return document;
	}
    /**
     * 输出XML
     * @param document
     * @param miniMongoDB
     * @throws Exception
     */
	public void outXML(Document document,MiniMongoDB miniMongoDB) throws Exception{
		XMLOutputter xmlOutputter = new XMLOutputter();
		xmlOutputter.output(document, new FileOutputStream(new File(miniMongoDB.dbPath)));
	}
	
	@Override
	public String toString() {
		return "MiniMongoDB [dbName=" + dbName + ", dbPath=" + dbPath + "]";
	}
}
